home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / Development / reportplus / source / f8.c < prev    next >
C/C++ Source or Header  |  2002-10-27  |  59KB  |  1,665 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <proto/exec.h>
  4. #include <intuition/intuition.h>
  5. #include <intuition/gadgetclass.h>
  6. #include <proto/intuition.h>
  7. #include <libraries/gadtools.h>
  8. #include <proto/gadtools.h>
  9. #include <dos/dos.h>
  10. #include <dos/exall.h>
  11. #include <dos/dostags.h>
  12. #include <proto/dos.h>
  13. #include <graphics/gfx.h>
  14. #include <clib/graphics_protos.h>
  15. #include <clib/alib_protos.h>
  16. #include <libraries/asl.h>
  17. #include <clib/asl_protos.h>
  18.  
  19. #include <ctype.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "rp.h"
  23.  
  24. #define ALL_REACTION_CLASSES
  25. #include <reaction/reaction.h>
  26.  
  27. #define TRUNCATE            39
  28. #define GRANULARITY_DIRS    10
  29. #define GRANULARITY_FILES   10
  30.  
  31. MODULE void parent(void);
  32. MODULE void root(void);
  33. MODULE void pathasl(void);
  34. MODULE void writeline(void);
  35. MODULE void killsizelist(void);
  36. MODULE void ghost(void);
  37. MODULE void unghost(void);
  38. MODULE void scale(ULONG bytes);
  39. // MODULE void __inline progressbar(ULONG level);
  40. MODULE void examine(STRPTR thename, ULONG nesting, ULONG parentdir);
  41. MODULE void AddSpecialNode(struct List* ListPtr, STRPTR pathname, ULONG nesting, ULONG size, ULONG parentdir, ULONG key, LONG type, LONG prot);
  42. MODULE void FreeSpecialNodes(struct List* ListPtr);
  43. MODULE void print_node(ULONG passedkey);
  44. MODULE void print_entry(struct SpecialNode* NodePtr);
  45. MODULE void print_list(ABOOL close);
  46. MODULE void busy(void);
  47.  
  48. #define UNITOPTIONS 3 // counting from 0
  49. MODULE STRPTR UnitOptions[UNITOPTIONS + 1] =
  50. {   "Bytes",
  51.     "Kilobytes",
  52.     "Megabytes",
  53.     "Blocks"
  54. };
  55.  
  56. MODULE struct SpecialNode
  57. {   struct Node Node;
  58.     ULONG       nesting,
  59.                 size,
  60.                 parentdir,
  61.                 key;
  62.     LONG        type,
  63.                 prot;
  64.     TEXT        pathname[1];
  65. };
  66.  
  67. MODULE struct ColumnInfo SizeColumnInfo[] =
  68. { { 75,            // WORD   ci_Width
  69.     "Pathname",    // STRPTR ci_Title
  70.     0,             // ULONG  ci_Flags
  71.   },
  72.   { 25,
  73.     "Size",
  74.     0, /* Last column must not have CIF_DRAGGABLE set (CIF_DRAGGABLE applies
  75.           to the right border of the relevant column). */
  76.   },
  77.   { -1, (STRPTR) ~0, -1
  78. } };
  79.  
  80. IMPORT struct TextAttr     Topaz8;
  81. IMPORT SBYTE               page;
  82. IMPORT TEXT                weekdaystring[LEN_DATSTRING],
  83.                            datestring[LEN_DATSTRING],
  84.                            timestring[LEN_DATSTRING],
  85.                            asldir[PATHNAMEFIELD + 1],
  86.                            aslresult[PATHNAMEFIELD + 1],
  87.                            IOBuffer[LONGESTFIELD + 1];
  88. IMPORT struct SharedStruct shared;
  89. IMPORT struct Screen*      ScreenPtr;
  90. IMPORT struct Window*      MainWindowPtr;
  91. IMPORT struct ExAllData*   EADataPtr;
  92. IMPORT struct Menu*        MenuPtr;
  93. IMPORT Object*             WinObject[FUNCTIONS + 1];
  94. IMPORT ULONG               increment;
  95.  
  96. AGLOBAL struct Gadget*     size_gadgets[GIDS_8 + 1];
  97. AGLOBAL struct SizeStruct  size =
  98. {   0, 0, 0, 0, 0, 0, 0,
  99.     (ULONG) FALSE, (ULONG) FALSE, (ULONG) FALSE,
  100.     "RAM:", "RAM:", "RAM:ReportPlus.log"
  101. };
  102.  
  103. MODULE struct List         SizeList,
  104.                            EmptySizeList,
  105.                            List1,
  106.                            List2;
  107. MODULE BPTR                DirHandle      = NULL,
  108.                            LogFileHandle  = NULL;
  109. MODULE TEXT                logstring[PATHNAMEFIELD + 1];
  110. MODULE UBYTE               commastring[13 + 1];
  111. MODULE ULONG               status         = STATUS_READY,
  112.                            key            = 0,
  113.                            topnesting     = 0,
  114.                            showall        = TRUE,
  115.                            showfiles      = TRUE;
  116.  
  117. AGLOBAL void size_init(void)
  118. {   struct ListBrowserNode* ListBrowserNodePtr;
  119.  
  120.     NewList(&List1);
  121.     NewList(&List2);
  122.     NewList(&SizeList);
  123.  
  124.     /* Create a 2-column listbrowser list with only one node containing
  125.     only column tags. */
  126.     NewList(&EmptySizeList);
  127.     if (!(ListBrowserNodePtr = AllocListBrowserNode
  128.     (   2,                  // columns
  129.         /* LBNCA_ tags are those that apply to the specific column. */
  130.         LBNA_Column,        0,
  131.         LBNA_Column,        1,
  132.         TAG_END
  133.     )))
  134.     {   rq("Can't create ReAction listbrowser.gadget node(s)!");
  135.     }
  136.     AddTail(&EmptySizeList, (struct Node *) ListBrowserNodePtr); // AddTail() has no return code
  137. }
  138.  
  139. AGLOBAL void size1(void)
  140. {   struct Hook         Hook8Struct;
  141.     struct List         ChooserList;
  142.     struct ChooserNode* ChooserNodePtr[UNITOPTIONS + 1];
  143.     ULONG               i;
  144.  
  145.     NewList(&ChooserList);
  146.     for (i = 0; i <= UNITOPTIONS; i++)
  147.     {   if (!(ChooserNodePtr[i] = (struct ChooserNode *) AllocChooserNode(CNA_Text, UnitOptions[i], TAG_DONE)))
  148.         {   rq("Can't allocate chooser node!");
  149.         }
  150.         AddTail(&ChooserList, (struct Node *) ChooserNodePtr[i]);
  151.     } // automatically freed by ReAction at DisposeObject() time
  152.  
  153.     InitHook(&Hook8Struct, Hook8Func, NULL);
  154.  
  155.     /* Create the window object. */
  156.     lockscreen();
  157.  
  158.     /* We can't just use EmptyList for an empty columnar list, we
  159.     actually need a node (with the LBNA_Column tags) to be present.
  160.  
  161.     LISTBROWSER_ScrollRaster seems not to be usable with
  162.     multi-column lists. */
  163.  
  164.     if (!(WinObject[8] =          NewObject(WINDOW_GetClass(), NULL,
  165.     // window
  166.     WA_PubScreen,                 ScreenPtr,
  167.     WA_ScreenTitle,               "Report+",
  168.     WA_Title,                     "Report+: Path Size Report",
  169.     WA_Activate,                  TRUE,
  170.     WA_DepthGadget,               TRUE,
  171.     WA_DragBar,                   TRUE,
  172.     WA_CloseGadget,               TRUE,
  173.     WA_SizeGadget,                TRUE,
  174.     WA_IDCMP,                     IDCMP_RAWKEY,
  175.     WINDOW_IDCMPHook,             &Hook8Struct,
  176.     WINDOW_IDCMPHookBits,         IDCMP_RAWKEY,
  177.     WINDOW_MenuStrip,             MenuPtr,
  178.     WINDOW_Position,              WPOS_CENTERSCREEN,
  179.     WINDOW_ParentGroup,           size_gadgets[GID_8_LY1] =
  180.     NewObject
  181.     (       LAYOUT_GetClass(), NULL,
  182.             // root-layout
  183.             LAYOUT_Orientation,        LAYOUT_ORIENT_VERT,
  184.             LAYOUT_SpaceOuter,         TRUE,
  185.             LAYOUT_DeferLayout,        TRUE,
  186.             LAYOUT_AddChild,
  187.             NewObject
  188.             (   LAYOUT_GetClass(),     NULL,
  189.                 LAYOUT_Orientation,    LAYOUT_ORIENT_HORIZ,
  190.                 LAYOUT_VertAlignment,  LALIGN_CENTER,
  191.                 LAYOUT_HorizAlignment, LALIGN_CENTER,
  192.                 LAYOUT_BevelStyle,     BVS_NONE,
  193.                 LAYOUT_AddImage,
  194.                 NewObject
  195.                 (   LABEL_GetClass(),  NULL,
  196.                     LABEL_Text,        "_Path:",
  197.                     LABEL_Justification,LJ_LEFT,
  198.                 TAG_END),
  199.                 CHILD_WeightedWidth,   0,
  200.                 LAYOUT_AddChild,       size_gadgets[GID_8_ST1] =
  201.                 NewObject
  202.                 (   STRING_GetClass(), NULL,
  203.                     GA_ID,             GID_8_ST1,
  204.                     GA_RelVerify,      TRUE,
  205.                     GA_TabCycle,       TRUE,
  206.                     STRINGA_TextVal,   size.path,
  207.                     STRINGA_MinVisible,20,
  208.                 TAG_END),
  209.                 LAYOUT_AddChild,       size_gadgets[GID_8_BU1] =
  210.                 NewObject(NULL,        "button.gadget",
  211.                     GA_ID,             GID_8_BU1,
  212.                     GA_RelVerify,      TRUE,
  213.                     BUTTON_AutoButton, BAG_POPFILE,
  214.                 TAG_END),
  215.                 CHILD_WeightedWidth,   0,
  216.             TAG_END),
  217.             CHILD_WeightedHeight,      0,
  218.             LAYOUT_AddChild,           NewObject(LAYOUT_GetClass(), NULL,
  219.                 LAYOUT_Orientation,    LAYOUT_ORIENT_HORIZ,
  220.                 LAYOUT_VertAlignment,  LALIGN_CENTER,
  221.                 LAYOUT_HorizAlignment, LALIGN_CENTER,
  222.                 LAYOUT_BevelStyle,     BVS_NONE,
  223.                 LAYOUT_ShrinkWrap,     TRUE,
  224.                 LAYOUT_AddChild,       size_gadgets[GID_8_CB1] =
  225.                 NewObject
  226.                 (   CHECKBOX_GetClass(),NULL,
  227.                     // checkbox
  228.                     GA_ID,             GID_8_CB1,
  229.                     GA_RelVerify,      TRUE,
  230.                     GA_Text,           "_Log to:",
  231.                     GA_Selected,       (BOOL) size.log,
  232.                     TAG_END
  233.                 ),
  234.                 CHILD_WeightedWidth,   0,
  235.                 LAYOUT_AddChild,       size_gadgets[GID_8_ST2] =
  236.                                        NewObject(STRING_GetClass(), NULL,
  237.                     // string        
  238.                     GA_ID,             GID_8_ST2,
  239.                     GA_RelVerify,      TRUE,
  240.                     GA_TabCycle,       TRUE,
  241.                     STRINGA_TextVal,   size.logfile,
  242.                     STRINGA_MinVisible,20,
  243.                     GA_Disabled,       !size.log,
  244.                     TAG_END
  245.                 ),
  246.                 LAYOUT_AddChild,       size_gadgets[GID_8_BU3] =
  247.                 NewObject
  248.                 (   NULL,              "button.gadget",
  249.                     // button
  250.                     GA_ID,             GID_8_BU3,
  251.                     GA_RelVerify,      TRUE,
  252.                     BUTTON_AutoButton, BAG_POPFILE,
  253.                     GA_Disabled,       !size.log,
  254.                     TAG_END
  255.                 ),
  256.                 CHILD_WeightedWidth,   0,
  257.                 TAG_END
  258.             ),
  259.             CHILD_WeightedHeight,      0,
  260.             LAYOUT_AddChild,
  261.             NewObject
  262.             (   LAYOUT_GetClass(),     NULL,
  263.                 LAYOUT_Orientation,    LAYOUT_ORIENT_VERT,
  264.                 LAYOUT_SpaceOuter,     TRUE,
  265.                 LAYOUT_VertAlignment,  LALIGN_CENTER,
  266.                 LAYOUT_HorizAlignment, LALIGN_CENTER,
  267.                 LAYOUT_BevelStyle,     BVS_FIELD,
  268.                 LAYOUT_AddChild,
  269.                 NewObject
  270.                 (   LAYOUT_GetClass(),     NULL,
  271.                     LAYOUT_Orientation,    LAYOUT_ORIENT_HORIZ,
  272.                     LAYOUT_VertAlignment,  LALIGN_CENTER,
  273.                     LAYOUT_HorizAlignment, LALIGN_CENTER,
  274.                     LAYOUT_BevelStyle,     BVS_NONE,
  275.                     LAYOUT_AddChild,       size_gadgets[GID_8_BU6] =
  276.                     NewObject
  277.                     (   NULL,              "button.gadget",
  278.                         GA_ID,             GID_8_BU6,
  279.                         GA_RelVerify,      TRUE,
  280.                         GA_Text,           "_Root",
  281.                         TAG_END
  282.                     ),
  283.                     CHILD_WeightedWidth,   50,
  284.                     LAYOUT_AddChild,       size_gadgets[GID_8_BU7] =
  285.                     NewObject             
  286.                     (   NULL,              "button.gadget",
  287.                         GA_ID,             GID_8_BU7,
  288.                         GA_RelVerify,      TRUE,
  289.                         GA_Text,           "P_arent",
  290.                         TAG_END
  291.                     ),
  292.                     CHILD_WeightedWidth,   50,
  293.                 TAG_END),
  294.                 CHILD_WeightedHeight,      0,
  295.                 LAYOUT_AddChild,           size_gadgets[GID_8_LB2] =
  296.                 NewObject
  297.                 (   LISTBROWSER_GetClass(),NULL,
  298.                     GA_ID,                 GID_8_LB2,
  299.                     GA_RelVerify,          TRUE,
  300.                     GA_TextAttr,           &Topaz8,
  301.                     LISTBROWSER_Labels,    (ULONG) &EmptySizeList,
  302.                     LISTBROWSER_ColumnInfo,(ULONG) &SizeColumnInfo,
  303.                     LISTBROWSER_ColumnTitles,TRUE,
  304.                     LISTBROWSER_MinVisible,6,
  305.                 TAG_END),
  306.                 CHILD_WeightedHeight,      100,
  307.                 CHILD_MinHeight,           160,
  308.                 LAYOUT_AddChild,
  309.                 NewObject
  310.                 (   LAYOUT_GetClass(),     NULL,
  311.                     LAYOUT_Orientation,    LAYOUT_ORIENT_HORIZ,
  312.                     LAYOUT_VertAlignment,  LALIGN_LEFT,
  313.                     LAYOUT_HorizAlignment, LALIGN_RIGHT,
  314.                     LAYOUT_BevelStyle,     BVS_NONE,
  315.                     LAYOUT_AddChild,
  316.                     NewObject
  317.                     (   LAYOUT_GetClass(),     NULL,
  318.                         LAYOUT_Orientation,    LAYOUT_ORIENT_VERT,
  319.                         LAYOUT_VertAlignment,  LALIGN_CENTER,
  320.                         LAYOUT_HorizAlignment, LALIGN_RIGHT,
  321.                         LAYOUT_BevelStyle,     BVS_NONE,
  322.                         LAYOUT_AddImage,
  323.                         NewObject
  324.                         (   LABEL_GetClass(),  NULL,
  325.                             LABEL_Text,        "Files:",
  326.                             LABEL_Justification,LJ_CENTRE,
  327.                         TAG_END),
  328.                         CHILD_WeightedHeight,  0,
  329.                         LAYOUT_AddImage,
  330.                         NewObject
  331.                         (   LABEL_GetClass(),  NULL,
  332.                             LABEL_Text,        "Directories:",
  333.                             LABEL_Justification,LJ_CENTRE,
  334.                         TAG_END),
  335.                         CHILD_WeightedHeight,  0,
  336.                         LAYOUT_AddImage,
  337.                         NewObject
  338.                         (   LABEL_GetClass(),  NULL,
  339.                             LABEL_Text,        "Block size:",
  340.                             LABEL_Justification,LJ_CENTRE,
  341.                         TAG_END),
  342.                         CHILD_WeightedHeight,  0,
  343.                     TAG_END),
  344.                     CHILD_WeightedWidth,       0,
  345.                     LAYOUT_AddChild,
  346.                     NewObject
  347.                     (   LAYOUT_GetClass(),     NULL,
  348.                         LAYOUT_Orientation,    LAYOUT_ORIENT_VERT,
  349.                         LAYOUT_VertAlignment,  LALIGN_CENTER,
  350.                         LAYOUT_HorizAlignment, LALIGN_RIGHT,
  351.                         LAYOUT_BevelStyle,     BVS_NONE,
  352.                         LAYOUT_AddChild,       size_gadgets[GID_8_ST6] =
  353.                         NewObject
  354.                         (   STRING_GetClass(), NULL,
  355.                             GA_ID,             GID_8_ST6,
  356.                             GA_ReadOnly,       TRUE,
  357.                             STRINGA_TextVal,   "-",
  358.                             STRINGA_MinVisible,13,
  359.                             STRINGA_Justification,GACT_STRINGRIGHT,
  360.                             GA_TextAttr,       &Topaz8,
  361.                         TAG_END),
  362.                         CHILD_WeightedHeight,  0,
  363.                         LAYOUT_AddChild,       size_gadgets[GID_8_ST7] =
  364.                         NewObject
  365.                         (   STRING_GetClass(), NULL,
  366.                             GA_ID,             GID_8_ST7,
  367.                             GA_ReadOnly,       TRUE,
  368.                             STRINGA_TextVal,   "-",
  369.                             STRINGA_MinVisible,13,
  370.                             STRINGA_Justification,GACT_STRINGRIGHT,
  371.                             GA_TextAttr,       &Topaz8,
  372.                         TAG_END),
  373.                         CHILD_WeightedHeight,  0,
  374.                         LAYOUT_AddChild,       size_gadgets[GID_8_ST8] =
  375.                         NewObject
  376.                         (   STRING_GetClass(), NULL,
  377.                             GA_ID,             GID_8_ST8,
  378.                             GA_ReadOnly,       TRUE,
  379.                             STRINGA_TextVal,   "-",
  380.                             STRINGA_MinVisible,13,
  381.                             STRINGA_Justification,GACT_STRINGRIGHT,
  382.                             GA_TextAttr,       &Topaz8,
  383.                         TAG_END),
  384.                         CHILD_WeightedHeight,  0,
  385.                     TAG_END),
  386.                     CHILD_WeightedWidth,       0,
  387.                     LAYOUT_AddImage,           NewObject
  388.                     (   LABEL_GetClass(),      NULL,
  389.                         LABEL_Text,            "",
  390.                         TAG_END
  391.                     ),
  392.                     CHILD_WeightedWidth,       100,
  393.                     LAYOUT_AddChild,
  394.                     NewObject
  395.                     (   LAYOUT_GetClass(),     NULL,
  396.                         LAYOUT_Orientation,    LAYOUT_ORIENT_VERT,
  397.                         LAYOUT_VertAlignment,  LALIGN_CENTER,
  398.                         LAYOUT_HorizAlignment, LALIGN_RIGHT,
  399.                         LAYOUT_BevelStyle,     BVS_NONE,
  400.                         LAYOUT_AddImage,
  401.                         NewObject
  402.                         (   LABEL_GetClass(),  NULL,
  403.                             LABEL_Text,        "Used in path:",
  404.                             LABEL_Justification,LJ_RIGHT,
  405.                         TAG_END),
  406.                         CHILD_WeightedHeight,  0,
  407.                         LAYOUT_AddImage,
  408.                         NewObject
  409.                         (   LABEL_GetClass(),  NULL,
  410.                             LABEL_Text,        "Free on volume:",
  411.                             LABEL_Justification,LJ_RIGHT,
  412.                         TAG_END),
  413.                         CHILD_WeightedHeight,  0,
  414.                         LAYOUT_AddImage,
  415.                         NewObject
  416.                         (   LABEL_GetClass(),  NULL,
  417.                             LABEL_Text,        "Volume capacity:",
  418.                             LABEL_Justification,LJ_RIGHT,
  419.                         TAG_END),
  420.                         CHILD_WeightedHeight,  0,
  421.                     TAG_END),
  422.                     CHILD_WeightedWidth,       0,
  423.                     LAYOUT_AddChild,
  424.                     NewObject
  425.                     (   LAYOUT_GetClass(),     NULL,
  426.                         LAYOUT_Orientation,    LAYOUT_ORIENT_VERT,
  427.                         LAYOUT_VertAlignment,  LALIGN_CENTER,
  428.                         LAYOUT_HorizAlignment, LALIGN_RIGHT,
  429.                         LAYOUT_BevelStyle,     BVS_NONE,
  430.                         LAYOUT_AddChild,       size_gadgets[GID_8_ST4] =
  431.                         NewObject
  432.                         (   STRING_GetClass(), NULL,
  433.                             GA_ID,             GID_8_ST4,
  434.                             GA_ReadOnly,       TRUE,
  435.                             STRINGA_TextVal,   "-",
  436.                             STRINGA_MinVisible,13,
  437.                             STRINGA_Justification,GACT_STRINGRIGHT,
  438.                             GA_TextAttr,       &Topaz8,
  439.                         TAG_END),
  440.                         CHILD_WeightedHeight,  0,
  441.                         LAYOUT_AddChild,       size_gadgets[GID_8_ST5] =
  442.                         NewObject
  443.                         (   STRING_GetClass(), NULL,
  444.                             GA_ID,             GID_8_ST5,
  445.                             GA_ReadOnly,       TRUE,
  446.                             STRINGA_TextVal,   "-",
  447.                             STRINGA_MinVisible,13,
  448.                             STRINGA_Justification,GACT_STRINGRIGHT,
  449.                             GA_TextAttr,       &Topaz8,
  450.                         TAG_END),
  451.                         CHILD_WeightedHeight,  0,
  452.                         LAYOUT_AddChild,       size_gadgets[GID_8_ST3] =
  453.                         NewObject
  454.                         (   STRING_GetClass(), NULL,
  455.                             GA_ID,             GID_8_ST3,
  456.                             GA_ReadOnly,       TRUE,
  457.                             STRINGA_TextVal,   "-",
  458.                             STRINGA_MinVisible,13,
  459.                             STRINGA_Justification,GACT_STRINGRIGHT,
  460.                             GA_TextAttr,       &Topaz8,
  461.                         TAG_END),
  462.                         CHILD_WeightedHeight,  0,
  463.                     TAG_END),
  464.                     CHILD_WeightedWidth,       0,
  465.                 TAG_END),
  466.                 CHILD_WeightedHeight,          0,
  467.             TAG_END),
  468.             CHILD_WeightedHeight,              70,
  469.             LAYOUT_AddChild,
  470.             NewObject
  471.             (   LAYOUT_GetClass(),     NULL,
  472.                 LAYOUT_Orientation,    LAYOUT_ORIENT_HORIZ,
  473.                 LAYOUT_VertAlignment,  LALIGN_CENTER,
  474.                 LAYOUT_HorizAlignment, LALIGN_CENTER,
  475.                 LAYOUT_BevelStyle,     BVS_NONE,
  476.                 LAYOUT_AddChild,       size_gadgets[GID_8_CB4] =
  477.                 NewObject
  478.                 (   CHECKBOX_GetClass(),NULL,
  479.                     // checkbox
  480.                     GA_ID,             GID_8_CB4,
  481.                     GA_RelVerify,      TRUE,
  482.                     GA_Text,           "Show s_ubdirectories?",
  483.                     GA_Selected,       (BOOL) showall,
  484.                 TAG_END),
  485.                 CHILD_WeightedWidth,   0,
  486.                 LAYOUT_AddChild,       size_gadgets[GID_8_CB5] =
  487.                 NewObject
  488.                 (   CHECKBOX_GetClass(),NULL,
  489.                     // checkbox
  490.                     GA_ID,             GID_8_CB5,
  491.                     GA_RelVerify,      TRUE,
  492.                     GA_Text,           "Show _files?",
  493.                     GA_Selected,       (BOOL) showfiles,
  494.                 TAG_END),
  495.                 CHILD_WeightedWidth,   0,
  496.                 LAYOUT_AddImage,       NewObject
  497.                 (   LABEL_GetClass(),  NULL,
  498.                     LABEL_Text,        "",
  499.                     TAG_END
  500.                 ),
  501.                 CHILD_WeightedWidth,   100,
  502.             TAG_END),
  503.             CHILD_WeightedHeight,      0,
  504.             LAYOUT_AddChild,
  505.             NewObject
  506.             (   LAYOUT_GetClass(),     NULL,
  507.                 LAYOUT_Orientation,    LAYOUT_ORIENT_HORIZ,
  508.                 LAYOUT_VertAlignment,  LALIGN_CENTER,
  509.                 LAYOUT_HorizAlignment, LALIGN_CENTER,
  510.                 LAYOUT_BevelStyle,     BVS_NONE,
  511.                 LAYOUT_AddImage,
  512.                 NewObject
  513.                 (   LABEL_GetClass(),  NULL,
  514.                     // label
  515.                     LABEL_Text,        "_View as:",
  516.                     LABEL_Justification,LJ_RIGHT,
  517.                 TAG_END),
  518.                 CHILD_WeightedWidth,   0,
  519.                 LAYOUT_AddChild,       size_gadgets[GID_8_CH1] =
  520.                 NewObject
  521.                 (   CHOOSER_GetClass(),NULL,
  522.                     GA_ID,             GID_8_CH1,
  523.                     GA_RelVerify,      TRUE,
  524.                     CHOOSER_PopUp,     TRUE,
  525.                     CHOOSER_Labels,    &ChooserList,
  526.                     CHOOSER_Selected,  size.view,
  527.                     TAG_END
  528.                 ),
  529.                 CHILD_WeightedWidth,   0,
  530.                 LAYOUT_AddChild,       size_gadgets[GID_8_CB2] =
  531.                 NewObject
  532.                 (   CHECKBOX_GetClass(),NULL,
  533.                     // checkbox
  534.                     GA_ID,             GID_8_CB2,
  535.                     GA_RelVerify,      TRUE,
  536.                     GA_Text,           "Include _slack?",
  537.                     GA_Selected,       (BOOL) size.slack,
  538.                 TAG_END),
  539.                 CHILD_WeightedWidth,   0,
  540.                 LAYOUT_AddImage,       NewObject
  541.                 (   LABEL_GetClass(),  NULL,
  542.                     LABEL_Text,        "",
  543.                     TAG_END
  544.                 ),
  545.                 CHILD_WeightedWidth,   100,
  546.             TAG_END),
  547.             CHILD_WeightedHeight,     0,
  548.             LAYOUT_AddChild,          size_gadgets[GID_8_CB3] =
  549.             NewObject
  550.             (   CHECKBOX_GetClass(),  NULL,
  551.                 GA_ID,                GID_8_CB3,
  552.                 GA_RelVerify,         TRUE,
  553.                 GA_Text,              "Fi_x protection bits?",
  554.                 GA_Selected,          (BOOL) size.fixprot,
  555.             TAG_END),
  556.             CHILD_WeightedHeight,     0,
  557.             LAYOUT_AddChild,          size_gadgets[GID_8_FG1] =
  558.             NewObject
  559.             (   FUELGAUGE_GetClass(), NULL,
  560.                 GA_ID,                GID_8_FG1,
  561.                 GA_Text,              "Ready.",
  562.                 FUELGAUGE_Level,      0,
  563.                 FUELGAUGE_Percent,    FALSE,
  564.                 FUELGAUGE_Justification,FGJ_CENTER,
  565.             TAG_END),
  566.             CHILD_WeightedHeight,     0,
  567.             LAYOUT_AddChild,
  568.             NewObject
  569.             (   LAYOUT_GetClass(),    NULL,
  570.                 LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  571.                 LAYOUT_VertAlignment, LALIGN_CENTER,
  572.                 LAYOUT_HorizAlignment,LALIGN_CENTER,
  573.                 LAYOUT_BevelStyle,    BVS_NONE,
  574.                 LAYOUT_AddChild,      size_gadgets[GID_8_BU4] =
  575.                 NewObject
  576.                 (   NULL,             "button.gadget",
  577.                     GA_ID,            GID_8_BU4,
  578.                     GA_RelVerify,     TRUE,
  579.                     GA_Text,          "_Update",
  580.                 TAG_END),
  581.                 LAYOUT_AddChild,      size_gadgets[GID_8_BU5] =
  582.                 NewObject
  583.                 (   NULL,             "button.gadget",
  584.                     GA_ID,            GID_8_BU5,
  585.                     GA_RelVerify,     TRUE,
  586.                     GA_Text,          "Stop",
  587.                     GA_Disabled,      TRUE,
  588.                 TAG_END),
  589.             TAG_END),
  590.             CHILD_WeightedHeight,     0,
  591.     TAG_END)
  592.     )))
  593.     {   rq("Can't create ReAction objects!");
  594.     }
  595.     unlockscreen();
  596.     openwindow();
  597.     ActivateLayoutGadget(size_gadgets[GID_8_LY1], MainWindowPtr, NULL, (Object) size_gadgets[GID_8_ST1]);
  598.  
  599.     loop();
  600.     closewindow();
  601.     size_exit();
  602. }
  603.  
  604. AGLOBAL void updatesize(void)
  605. {   ABOOL                 failed      = FALSE;
  606.     struct FileInfoBlock* FIBPtr      = NULL;
  607.     struct InfoData*      InfoDataPtr;
  608.     struct ExAllControl*  eac;
  609.     struct SpecialNode*   NodePtr;
  610.  
  611.     ghost();
  612.     SetGadgetAttrs
  613.     (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  614.         FUELGAUGE_Min,   0,
  615.         FUELGAUGE_Max,   100,
  616.         FUELGAUGE_Level, 12,
  617.         GA_Text,         "Initializing...",
  618.         TAG_END
  619.     );
  620.  
  621.     killsizelist();
  622.     if ((List1.lh_Head)->ln_Succ) // the list is non-empty
  623.     {   FreeSpecialNodes(&List1);
  624.     }
  625.     if ((List2.lh_Head)->ln_Succ) // the list is non-empty
  626.     {   FreeSpecialNodes(&List2);
  627.     }
  628.     topnesting = 0;
  629.  
  630.     // 1: Ghost relevant gadgets, for duration of the operation.
  631.  
  632.     SetGadgetAttrs
  633.     (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  634.         FUELGAUGE_Min,   0,
  635.         FUELGAUGE_Max,   100,
  636.         FUELGAUGE_Level, 33,
  637.         GA_Text,         "Reading directories...",
  638.         TAG_END
  639.     ); // we don't know how many files in advance...
  640.  
  641.     // 2: Now get a Lock() on the path.
  642.  
  643.     size.numdirs = size.numfiles = 0;
  644.     /* From RKRM I&A, p. 65: */
  645.     if
  646.     (   !(DirHandle = (BPTR) Lock(size.path, ACCESS_READ))
  647.      || !(FIBPtr    = AllocDosObject(DOS_FIB, NULL))
  648.      || !(            Examine(DirHandle, FIBPtr))
  649.      ||  (FIBPtr->fib_DirEntryType <= 0) // if not a directory
  650.     )
  651.     {   failed = TRUE;
  652.     }
  653.  
  654.     strcpy(size.oldpath, size.path);
  655.     if (FIBPtr)
  656.     {   FreeDosObject(DOS_FIB, FIBPtr);
  657.         // FIBPtr = NULL;
  658.     }
  659.     if (failed)
  660.     {   DisplayBeep(ScreenPtr);
  661.         unghost();
  662.  
  663.         strcpy(size.path, size.oldpath);
  664.         SetGadgetAttrs
  665.         (   size_gadgets[GID_8_ST1], MainWindowPtr, NULL,
  666.             STRINGA_TextVal, size.path,
  667.             TAG_END
  668.         );
  669.         SetGadgetAttrs
  670.         (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  671.             FUELGAUGE_Level, 0,
  672.             GA_Text,         "Failed!",
  673.             TAG_END
  674.         );
  675.         return;
  676.     }
  677.     SetGadgetAttrs
  678.     (   size_gadgets[GID_8_ST1], MainWindowPtr, NULL,
  679.         STRINGA_TextVal, size.path,
  680.         TAG_END
  681.     );
  682.  
  683.     /* 3: Now we call Info() to ascertain the free bytes.
  684.           InfoDataPtr must be longword-aligned. */
  685.  
  686.     if (!(InfoDataPtr = AllocVec(sizeof(struct InfoData), MEMF_CLEAR | MEMF_PUBLIC)))
  687.     {   rq("Out of memory!");
  688.     }
  689.     if (Info(DirHandle, InfoDataPtr))
  690.     {   size.blocksize = InfoDataPtr->id_BytesPerBlock;
  691.         size.free      =
  692.         (InfoDataPtr->id_NumBlocks - InfoDataPtr->id_NumBlocksUsed) *
  693.          InfoDataPtr->id_BytesPerBlock;
  694.         size.capacity  =
  695.          InfoDataPtr->id_NumBlocks *
  696.          InfoDataPtr->id_BytesPerBlock;
  697.     } else
  698.     {   rq("Can't get volume info!");
  699.     }
  700.     FreeVec(InfoDataPtr);
  701.     // InfoDataPtr = NULL;
  702.  
  703.     comma(size.blocksize, commastring);
  704.     SetGadgetAttrs // "dirs"
  705.     (   size_gadgets[GID_8_ST8], MainWindowPtr, NULL,
  706.         STRINGA_TextVal, commastring,
  707.         TAG_END
  708.     );
  709.  
  710.     /* 4: Now we are ready to begin the main part of the operation. */
  711.  
  712.     size.total = 0;
  713.  
  714.     // This must be allocated with AllocDosObject()
  715.     if (!(eac = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  716.     {   rq("Can't allocate DOS object!");
  717.     }
  718.  
  719.     // examine path
  720.     AddSpecialNode(&List1, "", 0, 0, 0, 0, ST_USERDIR, 0);
  721.     key = 0;
  722.     for (NodePtr = List1.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  723.     {   if (NodePtr->type == ST_USERDIR)
  724.         {   examine
  725.             (   NodePtr->pathname,
  726.                 NodePtr->nesting,
  727.                 NodePtr->key
  728.             );
  729.     }   }
  730.  
  731.     if (status == STATUS_BUSY)
  732.     {   busy();
  733.     }
  734.  
  735.     if (status != STATUS_BUSY)
  736.     {   SetGadgetAttrs // "used in path"
  737.         (   size_gadgets[GID_8_ST4], MainWindowPtr, NULL,
  738.             STRINGA_TextVal, "-",
  739.             TAG_END
  740.         );
  741.         SetGadgetAttrs // "free on volume"
  742.         (   size_gadgets[GID_8_ST5], MainWindowPtr, NULL,
  743.             STRINGA_TextVal, "-",
  744.             TAG_END
  745.         );
  746.         SetGadgetAttrs // "volume capacity"
  747.         (   size_gadgets[GID_8_ST3], MainWindowPtr, NULL,
  748.             STRINGA_TextVal, "-",
  749.             TAG_END
  750.         );
  751.         SetGadgetAttrs // "files"
  752.         (   size_gadgets[GID_8_ST6], MainWindowPtr, NULL,
  753.             STRINGA_TextVal, "-",
  754.             TAG_END
  755.         );
  756.         SetGadgetAttrs // "directories"
  757.         (   size_gadgets[GID_8_ST7], MainWindowPtr, NULL,
  758.             STRINGA_TextVal, "-",
  759.             TAG_END
  760.         );
  761.         SetGadgetAttrs // "block size"
  762.         (   size_gadgets[GID_8_ST8], MainWindowPtr, NULL,
  763.             STRINGA_TextVal, "-",
  764.             TAG_END
  765.         );
  766.         killsizelist();
  767.     }
  768.  
  769.     unghost();
  770.     SetGadgetAttrs
  771.     (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  772.         FUELGAUGE_Min,     0,
  773.         FUELGAUGE_Max,   100,
  774.         FUELGAUGE_Level, 100,
  775.         GA_Text,         "Done",
  776.         TAG_END
  777.     );
  778.  
  779.     if (LogFileHandle)
  780.     {   Close(LogFileHandle);
  781.         LogFileHandle = NULL;
  782. }   }
  783.  
  784. AGLOBAL void size_loop(ULONG gid)
  785. {   ULONG                   i, length;
  786.     STRPTR                  stringptr;
  787.     struct ListBrowserNode* NodePtr;
  788.  
  789.     switch(gid)
  790.     {
  791.     case GID_8_BU1: // path ASL
  792.         pathasl();
  793.     break;
  794.     case GID_8_BU3:
  795.         asl("~(#?.info)");
  796.         SetGadgetAttrs // `Log to file:' (string)
  797.         (   size_gadgets[GID_8_ST2], MainWindowPtr, NULL,
  798.             STRINGA_TextVal, size.logfile,
  799.         TAG_END);
  800.     break;
  801.     case GID_8_BU4: // update
  802.         updatesize();
  803.     break;
  804.     // GID_8_BU5 is stop
  805.     case GID_8_BU6:
  806.         root();
  807.     break;
  808.     case GID_8_BU7:
  809.         parent();
  810.     break;
  811.     case GID_8_ST1: // path string
  812.         if (!(GetAttr
  813.         (   STRINGA_TextVal, size_gadgets[GID_8_ST1], (ULONG *) &stringptr
  814.         )))
  815.         {   rq("Unsupported inquiry!"); // should never happen
  816.         }
  817.         strcpy(size.path, stringptr);
  818.         updatesize();
  819.     break;
  820.     case GID_8_ST2: // output string
  821.         if (!(GetAttr
  822.         (   STRINGA_TextVal, size_gadgets[GID_8_ST2], (ULONG *) &stringptr
  823.         )))
  824.         {   rq("Unsupported inquiry!"); // should never happen
  825.         }
  826.         strcpy(size.logfile, stringptr);
  827.     break;
  828.     case GID_8_CB1:
  829.         if (!(GetAttr
  830.         (   GA_Selected, size_gadgets[GID_8_CB1], &size.log
  831.         )))
  832.         {   rq("Unsupported inquiry!"); // should never happen
  833.         }
  834.  
  835.         SetGadgetAttrs // `Log to file:' (string)
  836.         (   size_gadgets[GID_8_ST2], MainWindowPtr, NULL,
  837.             GA_Disabled, !size.log,
  838.             TAG_END
  839.         );
  840.         /* For some reason, we need to explicitly refresh the string gadget
  841.         visuals here */
  842.         RefreshGadgets((struct Gadget *) size_gadgets[GID_8_ST2], MainWindowPtr, NULL);
  843.  
  844.         SetGadgetAttrs // `Log to file:' (ASL button)
  845.         (   size_gadgets[GID_8_BU3], MainWindowPtr, NULL,
  846.             GA_Disabled, !size.log,
  847.             TAG_END
  848.         );
  849.         if (size.log)
  850.         {   ActivateLayoutGadget(size_gadgets[GID_8_LY1], MainWindowPtr, NULL, (Object) size_gadgets[GID_8_ST2]);
  851.         }
  852.     break;
  853.     case GID_8_CB2:
  854.         if (!(GetAttr
  855.         (   GA_Selected, size_gadgets[GID_8_CB2], (ULONG *) &size.slack
  856.         )))
  857.         {   rq("Unsupported inquiry!"); // should never happen
  858.         }
  859.     break;
  860.     case GID_8_CB3:
  861.         if (!(GetAttr
  862.         (   GA_Selected, size_gadgets[GID_8_CB3], (ULONG *) &size.fixprot
  863.         )))
  864.         {   rq("Unsupported inquiry!"); // should never happen
  865.         }
  866.     break;
  867.     case GID_8_CB4:
  868.         if (!(GetAttr
  869.         (   GA_Selected, size_gadgets[GID_8_CB4], (ULONG *) &showall
  870.         )))
  871.         {   rq("Unsupported inquiry!"); // should never happen
  872.         }
  873.         print_list(TRUE);
  874.     break;
  875.     case GID_8_CB5:
  876.         if (!(GetAttr
  877.         (   GA_Selected, size_gadgets[GID_8_CB5], (ULONG *) &showfiles
  878.         )))
  879.         {   rq("Unsupported inquiry!"); // should never happen
  880.         }
  881.         print_list(TRUE);
  882.     break;
  883.     case GID_8_CH1:
  884.         if (!(GetAttr
  885.         (   CHOOSER_Selected, size_gadgets[GID_8_CH1], (ULONG *) &size.view
  886.         )))
  887.         {   rq("Unsupported inquiry!"); // should never happen
  888.         }
  889.         print_list(TRUE);
  890.     break;
  891.     case GID_8_LB2:
  892.         // We get a message even if the user clicked on an empty part of
  893.         // the gadget.
  894.  
  895.         if (!(GetAttr
  896.         (   LISTBROWSER_SelectedNode, size_gadgets[GID_8_LB2], (ULONG *) &NodePtr
  897.         )))
  898.         {   rq("Unsupported inquiry!"); // should never happen
  899.         }
  900.         if (NodePtr)
  901.         {   GetListBrowserNodeAttrs((struct Node *) NodePtr, LBNA_Column, 0, LBNCA_Text, &stringptr, TAG_DONE);
  902.             length = strlen(stringptr);
  903.             for (i = 0; i <= length; i++)
  904.             {   if (*(stringptr + i) == '*')
  905.                 {   if (!(AddPart(size.path, stringptr + i + 1, PATHNAMEFIELD)))
  906.                     {   rq("Can't add filename to pathname!");
  907.                     }
  908.                     updatesize();
  909.                     break;
  910.         }   }   }
  911.     break;
  912.     default:
  913.     break;
  914. }   }
  915.  
  916. AGLOBAL void size_exit(void)
  917. {   if (DirHandle)
  918.     {   UnLock(DirHandle);
  919.         DirHandle = NULL;
  920.     }
  921.     if (LogFileHandle)
  922.     {   Close(LogFileHandle);
  923.         LogFileHandle = NULL;
  924.     }
  925.     if ((List1.lh_Head)->ln_Succ) // the list is non-empty
  926.     {   FreeSpecialNodes(&List1);
  927.     }
  928.     if ((List2.lh_Head)->ln_Succ) // the list is non-empty
  929.     {   FreeSpecialNodes(&List2);
  930.     }
  931.  
  932.     // Only call this if the list gadget is detached or not present.
  933.     // (ie. after closewindow()).
  934.     if ((SizeList.lh_Head)->ln_Succ) // if the list is non-empty
  935.     {   clearreactionlist(&SizeList);
  936. }   }
  937.  
  938. AGLOBAL void size_die(void)
  939. {   if ((EmptySizeList.lh_Head)->ln_Succ) // if the list is non-empty
  940.     {   clearreactionlist(&EmptySizeList);
  941.     }
  942.  
  943.     IOBuffer[0]  = (UBYTE) size.log;
  944.     IOBuffer[6]  = (UBYTE) showfiles;
  945.     IOBuffer[15] = (UBYTE) showall;
  946.     IOBuffer[21] = (UBYTE) size.slack;
  947.     IOBuffer[22] = (UBYTE) size.view;
  948.     IOBuffer[24] = (UBYTE) size.fixprot;
  949. }
  950.  
  951. AGLOBAL void size_config(void)
  952. {   size.log     = (ULONG) IOBuffer[0];
  953.     showfiles    = (ULONG) IOBuffer[6];
  954.     showall      = (ULONG) IOBuffer[15];
  955.     size.slack   = (ULONG) IOBuffer[21];
  956.     size.view    = (ULONG) IOBuffer[22];
  957.     size.fixprot = (ULONG) IOBuffer[24];
  958. }
  959.  
  960. MODULE void parent(void)
  961. {   BPTR DirHandle,
  962.          ParentHandle;
  963.  
  964.     if (!(DirHandle = (BPTR) Lock(size.path, ACCESS_READ)))
  965.         rq("Can't lock directory!");
  966.     if (!(ParentHandle = ParentDir(DirHandle)))
  967.     {   /* It returned a NULL lock; ie. a lock on SYS:
  968.         That is not what we want. */
  969.         ParentHandle = DirHandle;
  970.     }
  971.     if (!NameFromLock(ParentHandle, size.path, PATHNAMEFIELD))
  972.         rq("Can't get name from lock!");
  973.     UnLock(DirHandle);
  974.     // DirHandle = NULL;
  975.  
  976.     updatesize();
  977. }
  978.  
  979. MODULE void root(void)
  980. {   BPTR  DirHandle,
  981.           ParentHandle;
  982.     ABOOL rootdone     = FALSE;
  983.  
  984.     if (!(DirHandle = (BPTR) Lock(size.path, ACCESS_READ)))
  985.         rq("Can't lock directory!");
  986.     do
  987.     {   if (!(ParentHandle = ParentDir(DirHandle)))
  988.         {   /* It returned a NULL lock; ie. a lock on SYS:
  989.                That is not what we want. */
  990.             ParentHandle = DirHandle;
  991.             rootdone = TRUE;
  992.         } else DirHandle = ParentHandle;
  993.     } while (!rootdone);
  994.     if (!NameFromLock(ParentHandle, size.path, PATHNAMEFIELD))
  995.         rq("Can't get name from lock!");
  996.     UnLock(DirHandle);
  997.     // DirHandle = NULL;
  998.  
  999.     updatesize();
  1000. }
  1001.  
  1002. MODULE void pathasl(void)
  1003. {   strcpy(asldir, size.path);
  1004.     if (dirasl()) // path for ASL must be valid?
  1005.     {   strcpy(size.path, aslresult);
  1006.         SetGadgetAttrs
  1007.         (   size_gadgets[GID_8_ST1], MainWindowPtr, NULL,
  1008.             STRINGA_TextVal, size.path,
  1009.             TAG_END
  1010.         );
  1011.         updatesize();
  1012. }   }
  1013.  
  1014. MODULE void writeline(void)
  1015. {   /* The file is opened just before the first call to writeline()
  1016.     (when the date, time, etc. is written). Then we keep the file open
  1017.     and do our scan. Then we write out the results a line at a time,
  1018.     then the free and total bytes. */
  1019.  
  1020.     if (FPuts(LogFileHandle, logstring))
  1021.     {   Close(LogFileHandle);
  1022.         LogFileHandle = NULL;
  1023.         rq("Can't append to file!");
  1024. }   }
  1025.  
  1026. MODULE void killsizelist(void)
  1027. {   SetGadgetAttrs
  1028.     (   size_gadgets[GID_8_LB2], MainWindowPtr, NULL,
  1029.         LISTBROWSER_Labels, &EmptySizeList,
  1030.         TAG_END
  1031.     );
  1032.     if ((SizeList.lh_Head)->ln_Succ) // if the list is non-empty
  1033.     {   clearreactionlist(&SizeList);
  1034. }   }
  1035.  
  1036. AGLOBAL ULONG Hook8Func(struct Hook *h, VOID *o, VOID *msg)
  1037. {   /* "When the hook is called, the data argument points to the
  1038.     window object and message argument to the IntuiMessage." */
  1039.  
  1040.     UWORD code, qual;
  1041.     ULONG scroll = 0; // to avoid spurious compiler warnings
  1042.  
  1043.     geta4(); // wait till here before doing anything
  1044.     code = ((struct IntuiMessage *) msg)->Code;
  1045.     qual = ((struct IntuiMessage *) msg)->Qualifier;
  1046.     switch(code)
  1047.     {
  1048.     case SCAN_HELP:
  1049.         if (status == STATUS_READY)
  1050.         {   helpabout();
  1051.         }
  1052.     break;
  1053.     case SCAN_ESCAPE:
  1054.         if (status == STATUS_READY)
  1055.         {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1056.             {   cleanexit(EXIT_SUCCESS);
  1057.             } else page = 0;
  1058.         } else
  1059.         {   // assert(status == STATUS_BUSY);
  1060.             status = STATUS_STOPPING;
  1061.         }
  1062.     break;
  1063.     case SCAN_P:
  1064.         ActivateLayoutGadget(size_gadgets[GID_8_LY1], MainWindowPtr, NULL, (Object) size_gadgets[GID_8_ST1]);
  1065.     break;
  1066.     case SCAN_V:
  1067.         if (status == STATUS_READY)
  1068.         {   if (!(qual & IEQUALIFIER_LSHIFT) && !(qual & IEQUALIFIER_RSHIFT))
  1069.             {   if (size.view < UNITOPTIONS)
  1070.                     size.view++;
  1071.                 else size.view = 0;
  1072.             } else
  1073.             {   if (size.view > 0)
  1074.                     size.view--;
  1075.                 else size.view = UNITOPTIONS;
  1076.             }
  1077.             SetGadgetAttrs
  1078.             (   size_gadgets[GID_8_CH1], MainWindowPtr, NULL,
  1079.                 CHOOSER_Selected, size.view,
  1080.                 TAG_END
  1081.             );
  1082.         }
  1083.     break;
  1084.     case SCAN_PERIOD:
  1085.         pathasl();
  1086.     break;
  1087.     case SCAN_UP:
  1088.         if (qual & IEQUALIFIER_CONTROL)
  1089.         {   scroll = LBP_TOP;
  1090.         } elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  1091.         {   scroll = LBP_PAGEUP;
  1092.         } else scroll = LBP_LINEUP;
  1093.     break;
  1094.     case SCAN_DOWN:
  1095.         if (qual & IEQUALIFIER_CONTROL)
  1096.         {   scroll = LBP_BOTTOM;
  1097.         } elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  1098.         {   scroll = LBP_PAGEDOWN;
  1099.         } else scroll = LBP_LINEDOWN;
  1100.     break;
  1101.     default:
  1102.     break;
  1103.     }
  1104.  
  1105.     if (code == SCAN_UP || code == SCAN_DOWN)
  1106.     {   SetGadgetAttrs
  1107.         (   size_gadgets[GID_8_LB2],      // pointer to gadget
  1108.             MainWindowPtr,                // pointer to window (not window object!)
  1109.             NULL,                         // pointer to requester
  1110.             LISTBROWSER_Position, scroll, // tags
  1111.             TAG_DONE                      // done
  1112.         );
  1113.     }
  1114.  
  1115.     return(1);
  1116. }
  1117.  
  1118. MODULE void ghost(void)
  1119. {   status = STATUS_BUSY;
  1120.  
  1121.     SetGadgetAttrs // "update"
  1122.     (   size_gadgets[GID_8_BU4], MainWindowPtr, NULL,
  1123.         GA_Disabled, TRUE,
  1124.         TAG_END
  1125.     );
  1126.     SetGadgetAttrs // "stop"
  1127.     (   size_gadgets[GID_8_BU5], MainWindowPtr, NULL,
  1128.         GA_Disabled, FALSE,
  1129.         TAG_END
  1130.     );
  1131. }
  1132.  
  1133. MODULE void unghost(void)
  1134. {   status = STATUS_READY;
  1135.  
  1136.     SetGadgetAttrs // "update"
  1137.     (   size_gadgets[GID_8_BU4], MainWindowPtr, NULL,
  1138.         GA_Disabled, FALSE,
  1139.         TAG_END
  1140.     );
  1141.     SetGadgetAttrs // "stop"
  1142.     (   size_gadgets[GID_8_BU5], MainWindowPtr, NULL,
  1143.         GA_Disabled, TRUE,
  1144.         TAG_END
  1145.     );
  1146. }
  1147.  
  1148. MODULE void scale(ULONG bytes)
  1149. {   if (size.view == 0) // bytes
  1150.     {   comma(bytes, commastring);
  1151.     } elif (size.view == 1) // kilobytes
  1152.     {   comma(bytes / 1024, commastring);
  1153.     } elif (size.view == 2) // megabytes
  1154.     {   comma(bytes / 1048576, commastring);
  1155.     } else
  1156.     {   // assert(size.view == 3); // blocks
  1157.         // assert(size.blocksize); // to avoid division by zero
  1158.         comma(bytes / size.blocksize, commastring);
  1159.         if (bytes % size.blocksize)
  1160.         {   comma((bytes / size.blocksize) + 1, commastring);
  1161.         } else // exactly on a block boundary
  1162.         {   comma(bytes / size.blocksize, commastring);
  1163. }   }   }
  1164.  
  1165. /*
  1166. MODULE void __inline progressbar(ULONG level)
  1167. {   if (!(level % increment))
  1168.     {   SetGadgetAttrs
  1169.         (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1170.             FUELGAUGE_Level, level,
  1171.             TAG_END
  1172.         );
  1173. }   }
  1174. */
  1175.  
  1176. MODULE void examine(STRPTR thename, ULONG nesting, ULONG parentdir)
  1177. {   BOOL                 more;      // BOOL, not ABOOL
  1178.     BPTR                 DirHandle; // = NULL;
  1179.     struct ExAllControl* eac;       // = NULL;
  1180.     struct ExAllData*    ead;
  1181.     ULONG                baselength    = strlen(size.path),
  1182.                          breakval,
  1183.                          thesize;
  1184.     TEXT                 activefile[PATHNAMEFIELD + 1],
  1185.                          lockstring[PATHNAMEFIELD + 1];
  1186.     LONG                 ed,
  1187.                          prot;
  1188.  
  1189.     breakval = ra_checkbreak();
  1190.     if (breakval == 2)
  1191.     {   cleanexit(EXIT_SUCCESS);
  1192.     } elif (breakval == 1)
  1193.     {   status = STATUS_STOPPING;
  1194.         SetGadgetAttrs
  1195.         (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1196.             GA_Text, "Stopping...",
  1197.             TAG_END
  1198.         );
  1199.     }
  1200.     if (status == STATUS_STOPPING)
  1201.     {   return;
  1202.     }
  1203.  
  1204.     strcpy(lockstring, size.path);
  1205.     strcat(lockstring, thename);
  1206.  
  1207.     if (!(DirHandle = (BPTR) Lock(lockstring, ACCESS_READ)))
  1208.     {   // Printf("Can't lock %s!\n", lockstring);
  1209.         rq("Can't lock directory!");
  1210.     }
  1211.     if (!(eac = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  1212.     {   UnLock(DirHandle);
  1213.         DirHandle = NULL;
  1214.         rq("Can't allocate DOS object!");
  1215.     }
  1216.  
  1217.     if (size.fixprot)
  1218.     {   ed = ED_PROTECTION; // we want name, type, size and protection
  1219.     } else
  1220.     {   ed = ED_SIZE;       // we want name, type and size
  1221.     }
  1222.  
  1223.     eac->eac_LastKey = 0;
  1224.     do
  1225.     {   more = ExAll(DirHandle, (struct ExAllData *) EADataPtr, 4096, ed, eac);
  1226.         if (!more && IoErr() != ERROR_NO_MORE_ENTRIES)
  1227.         {   FreeDosObject(DOS_EXALLCONTROL, eac);
  1228.             eac = NULL;
  1229.             UnLock(DirHandle);
  1230.             DirHandle = NULL;
  1231.             rq("Can't examine path!"); /* ExAll() failed abnormally */
  1232.         }
  1233.         if (eac->eac_Entries == 0)
  1234.         {   ; /* ExAll() failed normally with no entries */
  1235.             continue; /* more is USUALLY zero */
  1236.         }
  1237.         ead = (struct ExAllData *) EADataPtr;
  1238.  
  1239.         do
  1240.         {   /* use ead here */
  1241.  
  1242.             strcpy(activefile, lockstring);
  1243.             if (!AddPart(activefile, ead->ed_Name, PATHNAMEFIELD))
  1244.             {   FreeDosObject(DOS_EXALLCONTROL, eac);
  1245.                 eac = NULL;
  1246.                 UnLock(DirHandle);
  1247.                 DirHandle = NULL;
  1248.                 rq("Can't add filename/dirname to path!");
  1249.             }
  1250.             if (ead->ed_Type == ST_USERDIR)
  1251.             {   size.numdirs++;
  1252.                 if (!(size.numdirs % GRANULARITY_DIRS))
  1253.                 {   comma(size.numdirs, commastring);
  1254.                     SetGadgetAttrs
  1255.                     (   size_gadgets[GID_8_ST7], MainWindowPtr, NULL,
  1256.                         STRINGA_TextVal, commastring,
  1257.                         TAG_END
  1258.                     );
  1259.                 }
  1260.  
  1261.                 AddSpecialNode
  1262.                 (   &List1,                      // list
  1263.                     &activefile[baselength + 1], // filename
  1264.                     nesting + 1,                 // nesting
  1265.                     0,                           // size
  1266.                     parentdir,                   // parentdir
  1267.                     ++key,                       // key
  1268.                     ST_USERDIR,                  // type
  1269.                     0                            // protection bits
  1270.                 );
  1271.                 if (topnesting < nesting + 1)
  1272.                 {   topnesting = nesting + 1;
  1273.             }   }
  1274.             elif (ead->ed_Type == ST_FILE)
  1275.             {   size.numfiles++;
  1276.                 if (!(size.numfiles % GRANULARITY_FILES))
  1277.                 {   comma(size.numfiles, commastring);
  1278.                     SetGadgetAttrs
  1279.                     (   size_gadgets[GID_8_ST6], MainWindowPtr, NULL,
  1280.                         STRINGA_TextVal, commastring,
  1281.                         TAG_END
  1282.                     );
  1283.                 }
  1284.                 if (size.slack)
  1285.                 {   if (ead->ed_Size % size.blocksize == 0)
  1286.                     {   thesize = ead->ed_Size;
  1287.                     } else
  1288.                     {   thesize = ((ead->ed_Size / size.blocksize) + 1) * size.blocksize;
  1289.                 }   }
  1290.                 else
  1291.                 {   thesize = ead->ed_Size;
  1292.                 }
  1293.                 size.total += thesize;
  1294.  
  1295.                 if (size.fixprot)
  1296.                 {   prot = ead->ed_Prot;
  1297.                 } else
  1298.                 {   prot = 0;
  1299.                 }
  1300.  
  1301.                 AddSpecialNode
  1302.                 (   &List1,                      // list
  1303.                     &activefile[baselength + 1], // filename
  1304.                     nesting + 1,                 // nesting
  1305.                     thesize,                     // size
  1306.                     parentdir,                   // parentdir
  1307.                     ++key,                       // key
  1308.                     ST_FILE,                     // type
  1309.                     prot                         // protection bits
  1310.                 );
  1311.                 if (topnesting < nesting + 1)
  1312.                 {   topnesting = nesting + 1;
  1313.             }   }
  1314.  
  1315.             /* get next ead */
  1316.             ead = ead->ed_Next;
  1317.         } while(ead);
  1318.     } while(more);
  1319.  
  1320.     FreeDosObject(DOS_EXALLCONTROL, eac);
  1321.     // eac = NULL;
  1322.     UnLock(DirHandle);
  1323.     // DirHandle = NULL;
  1324. }
  1325.  
  1326. MODULE void AddSpecialNode(struct List* ListPtr, STRPTR pathname, ULONG nesting, ULONG size, ULONG parentdir, ULONG key, LONG type, LONG prot)
  1327. {   struct SpecialNode* NodePtr;
  1328.     ULONG               needed;
  1329.  
  1330.     needed = sizeof(struct SpecialNode) + strlen(pathname);
  1331.  
  1332.     if (!(NodePtr = AllocVec(needed, MEMF_CLEAR | MEMF_PUBLIC)))
  1333.         rq("Out of memory!");
  1334.     strcpy(NodePtr->pathname, pathname);
  1335.     NodePtr->nesting      = nesting;
  1336.     NodePtr->size         = size;
  1337.     NodePtr->parentdir    = parentdir;
  1338.     NodePtr->key          = key;
  1339.     NodePtr->type         = type;
  1340.     NodePtr->prot         = prot;
  1341.     NodePtr->Node.ln_Name = NULL;
  1342.     NodePtr->Node.ln_Type = NT_USER;
  1343.     NodePtr->Node.ln_Pri  = 0;
  1344.     AddTail((struct List *) ListPtr, (struct Node *) NodePtr);
  1345. }
  1346. MODULE void FreeSpecialNodes(struct List* ListPtr)
  1347. {   /* RKM Libraries, p. 496:
  1348.     
  1349.     "Free the entire list, including the header. The header is not
  1350.     updated as the list is freed. This function demonstrates how to
  1351.     avoid referencing freed memory when deallocating nodes." */
  1352.  
  1353.     struct SpecialNode *WorkNodePtr, *NextNodePtr;
  1354.     
  1355.     WorkNodePtr = (struct SpecialNode *) (ListPtr->lh_Head); /* first node */
  1356.     while (NextNodePtr = (struct SpecialNode *) (WorkNodePtr->Node.ln_Succ))
  1357.     {   FreeVec(WorkNodePtr);
  1358.         WorkNodePtr = NextNodePtr;
  1359.     }
  1360.     NewList(ListPtr);
  1361. }
  1362.  
  1363. MODULE void print_node(ULONG passedkey)
  1364. {   struct SpecialNode *NodePtr,
  1365.                        *ChildNodePtr;
  1366.  
  1367.     for (NodePtr = List2.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  1368.     {   if (NodePtr->key == passedkey)
  1369.         {   break;
  1370.     }   }
  1371.  
  1372.     if (NodePtr->key != 0)
  1373.     {   print_entry(NodePtr);
  1374.     }
  1375.  
  1376.     // print child dirs
  1377.     for (ChildNodePtr = List2.lh_Head; ChildNodePtr->Node.ln_Succ; ChildNodePtr = ChildNodePtr->Node.ln_Succ)
  1378.     {   if (ChildNodePtr->key != 0)
  1379.         {   if (ChildNodePtr->parentdir == passedkey && (showall || ChildNodePtr->nesting <= 1))
  1380.             {   if (ChildNodePtr->type == ST_USERDIR)
  1381.                 {   print_node(ChildNodePtr->key);
  1382.                 } elif (showfiles)
  1383.                 {   print_entry(ChildNodePtr);
  1384. }   }   }   }   }
  1385.  
  1386. MODULE void print_entry(struct SpecialNode* NodePtr)
  1387. {   ULONG                   i, length,
  1388.                             where = 0; // to avoid spurious compiler warnings
  1389.     struct ListBrowserNode* ListBrowserNodePtr;
  1390.  
  1391.     logstring[0] = 0;
  1392.     if (NodePtr->nesting >= 2)
  1393.     {   for (i = 2; i <= NodePtr->nesting; i++)
  1394.         {   strcat(logstring, " ");
  1395.     }   }
  1396.     if (NodePtr->type == ST_USERDIR)
  1397.     {   strcat(logstring, "*");
  1398.     } else
  1399.     {   strcat(logstring, "+");
  1400.     }
  1401.     
  1402.     strcat(logstring, FilePart(NodePtr->pathname));
  1403.  
  1404.     scale(NodePtr->size);
  1405.     for (i = 0; i <= 13; i++)
  1406.     {   if (commastring[i] != ' ')
  1407.         {   where = i; // where is index of first non-space character
  1408.             break;
  1409.     }   }
  1410.  
  1411.     if (!(ListBrowserNodePtr = AllocListBrowserNode
  1412.     (   2,                       // columns,
  1413.         LBNA_Column,             0,
  1414.             LBNCA_CopyText,      TRUE,
  1415.             LBNCA_Text,          logstring,
  1416.         LBNA_Column,             1,
  1417.             LBNCA_CopyText,      TRUE,
  1418.             LBNCA_Text,          &commastring[where],
  1419.             LBNCA_Justification, LCJ_RIGHT,
  1420.         TAG_END
  1421.     )))
  1422.     {   rq("Can't create ReAction listbrowser.gadget node(s)!");
  1423.     }
  1424.     AddTail(&SizeList, (struct Node *) ListBrowserNodePtr); // AddTail() has no return code
  1425.  
  1426.     if (size.log)
  1427.     {   length = strlen(logstring);
  1428.         if (length < 50)
  1429.         {   for (i = 1; i <= 41 - length; i++)
  1430.             {   strcat(logstring, " ");
  1431.         }   }
  1432.         strcat(logstring, commastring);
  1433.         strcat(logstring, "\n");
  1434.         writeline();
  1435. }   }
  1436.  
  1437. MODULE void print_list(ABOOL close)
  1438. {   getdate();
  1439.     if (size.log)
  1440.     {   strcpy(logstring, "Path: \"");
  1441.         strcat(logstring, size.path);
  1442.         strcat(logstring, "\" at ");
  1443.         strcat(logstring, timestring);
  1444.         strcat(logstring, " on ");
  1445.         strcat(logstring, weekdaystring);
  1446.         strcat(logstring, " ");
  1447.         strcat(logstring, datestring);
  1448.         strcat(logstring, ":\n");
  1449.         if (!(LogFileHandle = (BPTR) Open(size.logfile, MODE_READWRITE)))
  1450.             rq("Can't open file for appending!");
  1451.         Seek(LogFileHandle, 0, OFFSET_END);
  1452.         writeline();
  1453.     }
  1454.  
  1455.     killsizelist();
  1456.  
  1457.     print_node(0);
  1458.  
  1459.     SetGadgetAttrs
  1460.     (   size_gadgets[GID_8_LB2], MainWindowPtr, NULL,
  1461.         LISTBROWSER_Labels, &SizeList,
  1462.         TAG_END
  1463.     );
  1464.  
  1465.     scale(size.total);
  1466.     SetGadgetAttrs // "used in path"
  1467.     (   size_gadgets[GID_8_ST4], MainWindowPtr, NULL,
  1468.         STRINGA_TextVal, commastring,
  1469.         TAG_END
  1470.     );
  1471.     scale(size.free);
  1472.     SetGadgetAttrs // "free on volume"
  1473.     (   size_gadgets[GID_8_ST5], MainWindowPtr, NULL,
  1474.         STRINGA_TextVal, commastring,
  1475.         TAG_END
  1476.     );
  1477.     scale(size.capacity);
  1478.     SetGadgetAttrs // "volume capacity"
  1479.     (   size_gadgets[GID_8_ST3], MainWindowPtr, NULL,
  1480.         STRINGA_TextVal, commastring,
  1481.         TAG_END
  1482.     );
  1483.     comma(size.numfiles, commastring);
  1484.     SetGadgetAttrs // "files"
  1485.     (   size_gadgets[GID_8_ST6], MainWindowPtr, NULL,
  1486.         STRINGA_TextVal, commastring,
  1487.         TAG_END
  1488.     );
  1489.     comma(size.numdirs, commastring);
  1490.     SetGadgetAttrs // "dirs"
  1491.     (   size_gadgets[GID_8_ST7], MainWindowPtr, NULL,
  1492.         STRINGA_TextVal, commastring,
  1493.         TAG_END
  1494.     );
  1495.  
  1496.     if (size.log)
  1497.     {   strcpy(logstring, "\nUsed in path:                            ");
  1498.         scale(size.total);
  1499.         strcat(logstring, commastring);
  1500.         strcat(logstring, "\nFree on volume:                          "); // these must be adjusted according to TRUNCATE
  1501.         scale(size.free);
  1502.         strcat(logstring, commastring);
  1503.         strcat(logstring, "\nVolume capacity:                         "); // these must be adjusted according to TRUNCATE
  1504.         scale(size.capacity);
  1505.         strcat(logstring, commastring);
  1506.         strcat(logstring, "\nFiles:                                   "); // these must be adjusted according to TRUNCATE
  1507.         comma(size.numfiles, commastring);
  1508.         strcat(logstring, commastring);
  1509.         strcat(logstring, "\nDirectories:                             "); // these must be adjusted according to TRUNCATE
  1510.         comma(size.numdirs, commastring);
  1511.         strcat(logstring, commastring);
  1512.         strcat(logstring, "\nBlock size:                              "); // these must be adjusted according to TRUNCATE
  1513.         comma(size.blocksize, commastring);
  1514.         strcat(logstring, commastring);
  1515.         strcat(logstring, "\n\n");
  1516.         writeline();
  1517.     }
  1518.     if (close && LogFileHandle)
  1519.     {   Close(LogFileHandle);
  1520.         LogFileHandle = NULL;
  1521. }   }
  1522.  
  1523. MODULE void busy(void)
  1524. {   ULONG               breakval, largestsize,
  1525.                         largestkey = 0; // to avoid spurious compiler warnings
  1526.     SLONG               nesting;
  1527.     struct SpecialNode *NodePtr,
  1528.                        *ParentNodePtr;
  1529.     TEXT                activefile[PATHNAMEFIELD + 1];
  1530.  
  1531.     if (size.fixprot)
  1532.     {   SetGadgetAttrs
  1533.         (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1534.             FUELGAUGE_Min,   0,
  1535.             FUELGAUGE_Max,   100,
  1536.             FUELGAUGE_Level, 45,
  1537.             GA_Text,         "Fixing protection bits...",
  1538.             TAG_END
  1539.         );
  1540.  
  1541.         if ((List1.lh_Head)->ln_Succ) // the list is non-empty
  1542.         {   // walk the files list
  1543.             for (NodePtr = List1.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  1544.             {   if (NodePtr->type == ST_FILE)
  1545.                 {   /* The rwed bits are SET to DENY access,
  1546.                     CLEARED to PERMIT access.
  1547.  
  1548.                     128 064 032 016 008 004 002 001
  1549.                     -H- -S- -P- -A- -R- -W- -E- -D- */
  1550.  
  1551.                     if
  1552.                     (   (NodePtr->prot & FIBF_READ)
  1553.                      || (NodePtr->prot & FIBF_WRITE)
  1554.                      || (NodePtr->prot & FIBF_EXECUTE)
  1555.                      || (NodePtr->prot & FIBF_DELETE)
  1556.                     )
  1557.                     {   NodePtr->prot &= ~FIBF_READ;
  1558.                         NodePtr->prot &= ~FIBF_WRITE;
  1559.                         NodePtr->prot &= ~FIBF_EXECUTE;
  1560.                         NodePtr->prot &= ~FIBF_DELETE;
  1561.  
  1562.                         strcpy(activefile, size.path);
  1563.                         if (!AddPart(activefile, NodePtr->pathname, PATHNAMEFIELD))
  1564.                         {   rq("Can't add filename to pathname!");
  1565.                         }
  1566.  
  1567.                         if (!(SetProtection(activefile, NodePtr->prot)))
  1568.                         {   rq("Can't fix protection bits!");
  1569.     }   }   }   }   }   }
  1570.  
  1571.     SetGadgetAttrs
  1572.     (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1573.         FUELGAUGE_Min,   0,
  1574.         FUELGAUGE_Max,   100,
  1575.         FUELGAUGE_Level, 50,
  1576.         GA_Text,         "Calculating sizes...",
  1577.         TAG_END
  1578.     );
  1579.  
  1580.     // calculate sizes
  1581.     for (nesting = topnesting; nesting >= 0; nesting--)
  1582.     {   breakval = ra_checkbreak();
  1583.         if (breakval == 2)
  1584.         {   cleanexit(EXIT_SUCCESS);
  1585.         } elif (breakval == 1)
  1586.         {   status = STATUS_STOPPING;
  1587.             SetGadgetAttrs
  1588.             (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1589.                 GA_Text, "Stopping...",
  1590.                 TAG_END
  1591.             );
  1592.         }
  1593.         if (status == STATUS_STOPPING)
  1594.         {   return;
  1595.         }
  1596.  
  1597.         // walk the files list
  1598.         for (NodePtr = List1.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  1599.         {   if (NodePtr->nesting == nesting)
  1600.             {   for (ParentNodePtr = List1.lh_Head; ParentNodePtr->Node.ln_Succ; ParentNodePtr = ParentNodePtr->Node.ln_Succ)
  1601.                 {   if (ParentNodePtr->type == ST_USERDIR && ParentNodePtr->key == NodePtr->parentdir)
  1602.                     {    break;
  1603.                 }   }
  1604.                 ParentNodePtr->size += NodePtr->size;
  1605.     }   }   }
  1606.  
  1607.     SetGadgetAttrs
  1608.     (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1609.         FUELGAUGE_Min,   0,
  1610.         FUELGAUGE_Max,   100,
  1611.         FUELGAUGE_Level, 66,
  1612.         GA_Text,         "Sorting results...",
  1613.         TAG_END
  1614.     );
  1615.  
  1616.     // sort by size
  1617.     while ((List1.lh_Head)->ln_Succ) // while the list is non-empty
  1618.     {   breakval = ra_checkbreak();
  1619.         if (breakval == 2)
  1620.         {   cleanexit(EXIT_SUCCESS);
  1621.         } elif (breakval == 1)
  1622.         {   status = STATUS_STOPPING;
  1623.             SetGadgetAttrs
  1624.             (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1625.                 GA_Text, "Stopping...",
  1626.                 TAG_END
  1627.             );
  1628.         }
  1629.         if (status == STATUS_STOPPING)
  1630.         {   return;
  1631.         }
  1632.  
  1633.         // walk through the list to determine the largest entry
  1634.         largestsize = 0;
  1635.         for (NodePtr = List1.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  1636.         {   if (NodePtr->size >= largestsize)
  1637.             {   largestsize = NodePtr->size;
  1638.                 largestkey  = NodePtr->key;
  1639.         }   }
  1640.  
  1641.         // walk through the list and remove the largest entry
  1642.         for (NodePtr = List1.lh_Head; NodePtr->Node.ln_Succ; NodePtr = NodePtr->Node.ln_Succ)
  1643.         {   if (NodePtr->key == largestkey)
  1644.             {   Remove((struct Node *) NodePtr);
  1645.                 AddTail(&List2, (struct Node *) NodePtr);
  1646.                 break;
  1647.     }   }   }
  1648.  
  1649.     SetGadgetAttrs
  1650.     (   size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
  1651.         FUELGAUGE_Min,   0,
  1652.         FUELGAUGE_Max,   100,
  1653.         FUELGAUGE_Level, 75,
  1654.         GA_Text,         "Generating list...",
  1655.         TAG_END
  1656.     );
  1657.     SetGadgetAttrs // "stop"
  1658.     (   size_gadgets[GID_8_BU5], MainWindowPtr, NULL,
  1659.         GA_Disabled, TRUE,
  1660.         TAG_END
  1661.     );
  1662.     print_list(FALSE);
  1663. }
  1664.  
  1665.